Module Architecture
flowchart TD
OC["Odoo Core\nbase · mail · web · queue_job"]
RS["sadeem.root.server\nSSH root server\nmonitoring · code server"]
PG["sadeem.postgresql.server\nremote DB connection config"]
ML["sadeem.root.server.monitor.log\nCPU · RAM · Disk · Network logs"]
GA["sadeem.saas.git.account\nGitHub credentials\nAPI token"]
GR["sadeem.saas.git.repository\nbranch management\nwebhook · code push"]
GC["sadeem.saas.git.commit\ncommit records\nbranch · message"]
BS["sadeem.saas.backup.server\nremote backup API\nAPI key auth"]
CA["sadeem.saas.backup.cloud.account\nS3 / cloud accounts\nsynced from backup server"]
NT["sadeem.ntfy.server\nntfy / Firebase FCM\ntoken management"]
WH["sadeem.saas.webhook\ninbound webhook endpoint\ntrigger record actions"]
LG["sadeem.saas.action.log\naudit trail\nSSH command results"]
OC --> RS
OC --> GA
OC --> BS
OC --> NT
RS --> A1([action_confirm\ntest SSH connection])
RS --> A2([action_run_cmd\nexecute remote command])
RS --> A3([action_start_monitor\nstart cron monitoring])
RS --> A4([action_install_code_server\ndeploy VS Code via SSH])
RS --> A5([action_setup_dir_structure\ninitialize server directories])
RS --> ML
RS --> PG
GA --> GR
GR --> GC
GR --> A6([action_push_code\npush addons via SSH])
GR --> A7([action_register_webhook\nregister GitHub webhook])
BS --> A8([action_test_connection\nHTTP ping backup API])
BS --> A9([action_sync_cloud_accounts\nfetch S3 accounts from remote])
BS --> CA
NT --> A10([action_send_notification\npush to ntfy / FCM])
WH --> A11([action_trigger\ncall record method on event])
RS --> LG
WH --> LG
Module Description
SAAS Base is the foundation of the Sadeem SAAS Package. It provides all shared
infrastructure that every other SAAS module builds on.
| Area |
What it does |
| Root Servers |
SSH connectivity, command execution, real-time monitoring (CPU/RAM/Disk/Network), web terminal, VS Code server |
| Git Integration |
GitHub account management, repository tracking, webhook registration, commit logging, syntax-validated code deployment |
| PostgreSQL Servers |
Remote database server connection configuration |
| Backup Servers |
Remote backup API integration with S3/cloud account syncing |
| Notification Servers |
Push notifications via self-hosted ntfy and Firebase FCM, per-subscription token management |
| Webhooks |
Inbound webhook endpoints that trigger actions on Odoo records |
| Audit Logging |
Full log of all SSH commands and server actions |
Dependencies
- mail — chatter, tracking, activity mixin
- queue_job — asynchronous job queue (used for background SSH operations)
Security Groups
| Group |
Implies |
Access Level |
| User |
— |
Read access, basic operations |
| Operator |
User |
Enhanced operations, backup server management |
| Administrator |
Operator |
Full access, git/webhook management, settings |
SAAS Management
├─ Git
⎢ ├─ Accounts
⎢ ├─ Repositories
⎢ └─ Git Commits
├─ Infrastructure
⎢ ├─ Servers
⎢ ⎢ ├─ Root Servers
⎢ ⎢ └─ Root Servers Dashboard
⎢ ├─ Database Servers
⎢ ⎢ └─ PostgreSQL Servers
⎢ └─ Backup Servers
⎢ └─ Backup Servers
├─ Notification Servers
└─ Configuration
└─ Settings
Configuration
Settings available under SAAS Management > Configuration > Settings
| Setting |
Type |
Default |
Description |
| Keep Root Server Log Period |
Integer |
2 |
Days to retain server monitoring logs before auto-cleanup |
| DNS Resolver |
Selection |
cloudflare |
DNS resolver for domain lookups: cloudflare, google, or local |
Key Fields
Root Server (sadeem.root.server)
| Field |
Type |
Description |
| ip |
Char |
Server IP address (required) |
| username |
Char |
SSH username (default: root) |
| password |
Char |
SSH password (one of password or RSA key required) |
| key |
Text |
RSA private key for SSH authentication |
| port |
Integer |
SSH port (default: 22) |
| state |
Selection |
Connection status: draft, confirmed, cancel |
| sudo_user |
Boolean |
Whether to run commands with sudo |
| sudo_user_no_password |
Boolean |
Whether sudo requires no password |
| uuid |
Char |
Unique identifier (auto-generated, used by monitoring script) |
| monitoring_enabled |
Boolean |
Whether real-time monitoring is active |
| monitor_update_interval |
Selection |
Monitoring poll interval (options: 5s, 10s, 30s, 1m, 5m) |
| server_state |
Selection |
Live health: no_monitor, online, warning, offline |
| code_server_port |
Integer |
Port for VS Code web server (default: 8080) |
| code_server_password |
Char |
Password to access VS Code server |
| code_server_domain |
Char |
Domain/URL for VS Code server |
| code_server_state |
Selection |
VS Code server status: not_installed, installed, running |
| dir_init_done |
Boolean |
Whether server directory structure has been initialized |
| cmd |
Char |
Last command run via action_run_cmd |
| cmd_output |
Text |
Output of last command |
PostgreSQL Server (sadeem.postgresql.server)
| Field |
Type |
Description |
| ip |
Char |
Database server IP (required) |
| username |
Char |
PostgreSQL username |
| password |
Char |
PostgreSQL password |
| port |
Integer |
PostgreSQL port (default: 5432) |
Backup Server (sadeem.saas.backup.server)
| Field |
Type |
Description |
| url |
Char |
Base URL of the remote backup API (required) |
| download_url |
Char |
Public download URL for backup files (required) |
| api_key |
Char |
API key for authenticating with the remote backup server (required) |
| drop_db_path |
Char |
API path for dropping a database (default: /sadeem/database/drop) |
| backup_db_path |
Char |
API path for creating a backup (default: /sadeem/database/backup) |
| restore_db_path |
Char |
API path for restoring a database (default: /sadeem/database/restore) |
| enable_local_backup |
Boolean |
Whether to store backups locally on backup server |
| enable_cloud_backup |
Boolean |
Whether to push backups to cloud/S3 storage |
| cloud_account_ids |
One2many |
List of synced cloud storage accounts |
Backup Cloud Account (sadeem.saas.backup.cloud.account)
| Field |
Type |
Description |
| uuid |
Char |
UUID matching the remote sadeem.saas.backup.storage.account record |
| remote_id |
Char |
Remote record ID on the backup server |
| provider |
Char |
Cloud provider name (e.g., S3, Backblaze) |
| backup_server_id |
Many2one |
The backup server this account belongs to |
Notification Server (sadeem.ntfy.server)
| Field |
Type |
Description |
| provider |
Selection |
ntfy (self-hosted) or fcm (Firebase Cloud Messaging) |
| url |
Char |
ntfy server base URL (required for ntfy provider) |
| is_default |
Boolean |
Whether this is the system-wide default notification server |
| auto_generate_tokens |
Boolean |
Automatically create per-user ntfy tokens |
| token_expiry_days |
Integer |
Days before auto-generated tokens expire (1–3650) |
| auth_enabled |
Boolean |
Whether ntfy server requires authentication |
| auth_method |
Selection |
password or token authentication |
| username / password |
Char |
Admin credentials for ntfy (used to create tokens) |
| auth_token |
Char |
Static auth token (when auth_method = token) |
| fcm_project_id |
Char |
Firebase project ID (for FCM provider) |
| fcm_server_key |
Char |
Firebase server key (legacy FCM) |
| fcm_service_account_json |
Text |
Firebase service account JSON (modern FCM) |
Git Account (sadeem.saas.git.account)
| Field |
Type |
Description |
| access_token |
Char |
GitHub personal access token (required) |
| git_provider |
Selection |
Currently only github |
| user_id |
Many2one |
Odoo user who owns this account |
Git Repository (sadeem.saas.git.repository)
| Field |
Type |
Description |
| branch_name |
Char |
Default branch to track (required) |
| git_account |
Many2one |
Git account used for API calls |
| webhook_id |
Char |
GitHub webhook ID (set after registration) |
| last_commit_id |
Many2one |
Most recent commit record |
| state |
Selection |
draft, active, cancel |
Git Commit (sadeem.saas.git.commit)
| Field |
Type |
Description |
| commit_id |
Char |
Git commit SHA |
| commit_message |
Char |
Commit message text |
| commit_by |
Char |
Author of the commit |
| branch |
Char |
Branch the commit was pushed to |
| repository_id |
Many2one |
Repository this commit belongs to |
Webhook (sadeem.saas.webhook)
| Field |
Type |
Description |
| token |
Char |
Secret token to authenticate inbound webhook calls |
| model_name |
Char |
Odoo model the webhook fires actions on |
| rec_id |
Integer |
Record ID to act on |
| trigger_action |
Char |
Method name to call on the target record |
| message_type |
Selection |
How to log the event: notification, comment, email |
| subtype_xmlid |
Selection |
Chatter subtype for message logging |
Action Log (sadeem.saas.action.log)
| Field |
Type |
Description |
| model_name |
Char |
Model the action was run against |
| rec_id |
Integer |
Record ID the action targeted |
| input_text |
Text |
Command or input that was sent |
| output_text |
Text |
Result or output received |
| action_type |
Selection |
Category of the action (e.g., SSH command, API call) |
Lifecycle & States
Root Server States
| State |
Meaning |
draft |
Initial state — server not yet verified |
confirmed |
SSH connection tested successfully |
cancel |
Server disabled / archived |
Transitions:
- draft → confirmed: action_confirm — tests SSH connection via paramiko; raises UserError if no credentials or connection fails
- confirmed → draft: action_reset_draft
- confirmed → cancel: action_cancel
Git Repository States
| State |
Meaning |
draft |
Repository not yet linked to GitHub |
active |
Webhook registered, tracking commits |
cancel |
Repository deactivated |
Transitions:
- draft → active: action_link_git_webhook — registers GitHub webhook via API
- active → draft: action_delete_git_webhook — removes GitHub webhook
Key Actions
| Action |
Model |
Description |
action_confirm |
sadeem.root.server |
Tests SSH connection (paramiko); moves server to confirmed state |
action_reset_draft |
sadeem.root.server |
Resets server to draft state |
action_cancel |
sadeem.root.server |
Cancels / disables the server |
action_run_cmd |
sadeem.root.server |
Executes cmd field value via SSH; output saved to cmd_output |
action_start_monitor |
sadeem.root.server |
Creates a cron job to poll CPU/RAM/Disk/Network metrics |
action_stop_monitor |
sadeem.root.server |
Removes monitoring cron job |
action_install_code_server |
sadeem.root.server |
Installs VS Code server on remote host via SSH |
action_remove_code_server |
sadeem.root.server |
Stops and removes VS Code server |
action_open_code_server |
sadeem.root.server |
Returns URL action to open VS Code in browser |
action_setup_dir_structure |
sadeem.root.server |
Creates standard /opt/odoo/... directory layout on server |
action_link_git_webhook |
sadeem.saas.git.repository |
Registers a GitHub webhook for push events |
action_delete_git_webhook |
sadeem.saas.git.repository |
Deletes the registered GitHub webhook |
action_push_commit |
sadeem.saas.git.repository |
Pushes addon code to server via SSH (syntax-validated) |
action_test_connection |
sadeem.saas.backup.server |
Sends HTTP ping to the remote backup API |
action_sync_cloud_accounts |
sadeem.saas.backup.server |
Fetches S3/cloud accounts from the remote backup server and syncs locally |
action_send_notification |
sadeem.ntfy.server |
Sends push notification via ntfy or FCM |
action_test_connection |
sadeem.ntfy.server |
Tests connectivity to the ntfy/FCM endpoint |
action_test_admin_credentials |
sadeem.ntfy.server |
Validates ntfy admin username/password |
action_trigger |
sadeem.saas.webhook |
Calls the configured method on the target record |
Warnings & Important Notes
- SSH credentials required:
action_confirm raises UserError if neither password nor key is provided.
- SSH connection failure:
action_confirm raises UserError with the SSH error message if paramiko cannot connect.
- Repository deletion blocked: Cannot delete a
sadeem.saas.git.repository while a webhook is still registered — raises ValidationError instructing the user to unlink the webhook first.
- Repository webhook registration: Requires a non-empty
access_token on the git account and both name and branch_name on the repository — ValidationError otherwise.
- ntfy URL required:
@api.constrains raises ValidationError if provider is ntfy and no URL is set, or URL does not start with http:// or https://.
- FCM credentials required:
@api.constrains raises ValidationError if provider is fcm and none of fcm_server_key, fcm_project_id, or fcm_service_account_json is set; also validates the JSON structure if service account JSON is provided.
- ntfy auto-generate requires admin credentials:
@api.constrains raises ValidationError if auto_generate_tokens is enabled without admin_username and admin_password.
- ntfy auth validation:
@api.constrains checks that auth credentials match the configured auth_method; raises ValidationError for missing password, token, or username.
- Token expiry range:
token_expiry_days must be between 1 and 3650; @api.constrains enforces this.
- Root server UUID uniqueness:
_sql_constraints enforces UNIQUE(uuid) on sadeem.root.server.
- Webhook token uniqueness:
_sql_constraints enforces UNIQUE(token) on sadeem.saas.webhook.
- ntfy server uniqueness:
_sql_constraints enforces one default notification server per company.
- Post-install hook: On installation, a secret key is generated via
sadeem_post_init_hook_secret_key — used for encrypting sensitive fields.